home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1994-05-01 | 36.1 KB | 1,037 lines | [ TEXT/ZBAS]
' ' FBSpriteWorld.incl by Robert Hommel ' © Copyright 1994 ' All rights granted for any use whatsoever ' ' version 1.01b ' ' Disclaimer: I've tested these routines quite thoroughly on my Mac ' LC running System 7.01 and FB 1.02c. I make no promises or warranties ' of any kind. ' '********************************************************************* ' COMPILE 0, _MacsBugLabels _caseInsensitive _STRResource INCLUDE FILE _aplIncl DEFSTR LONG DEFINT A-Z ' '--------------------------- GLOBALS --------------------------------- ' GLOBALS "FBSpriteWorld.glbl" END GLOBALS ' '------------------------- INCLUDE FILES ----------------------------- ' INCLUDE "TimeManager.incl" INCLUDE "GraphicUtils.incl" ' '--------------------------- FUNCTIONS ------------------------------- ' '--------------------------------------------------------------------- ' SWEnterSpriteWorld '--------------------------------------------------------------------- ' ' Make sure we can run in this environment. ' LOCAL MODE LOCAL FN SWEnterSpriteWorld LONG IF SYSTEM(_sysVers) > 700 AND SYSTEM(_maxColors) = 32 tmp = FN GESTALT(_gestaltTimeMgrVersion) IF tmp < _gestaltStandardTimeMgr THEN err=_swTimeMgrNotPresent ELSE err=_noErr XELSE err = _swNotSystemSeven END IF END FN = err ' '--------------------------------------------------------------------- ' SWGetBestPort '--------------------------------------------------------------------- ' ' Returns a pointer to a grafport based on the current screen depth. ' LOCAL MODE LOCAL FN SWGetBestPort&(rectPtr&) 'Returns a pointer to a grafport based on the current screen depth. END FN = FN GetOffScrnGWorld(rectPtr&) ' '--------------------------------------------------------------------- ' SWInitSpriteWorld '--------------------------------------------------------------------- ' ' Given a valid SpriteWorld pointer, this function creates all ' associated frames and sets the boundsRect. Returns appropriate ' error code. ' LOCAL MODE LOCAL FN SWCreateSpriteWorld(spriteWorldPtr&,srcPort&,rectPtr&,pictHdl&) ' spriteWorldPtr&.boundsRect%;8 = rectPtr& 'set boundsRect ' spriteWorldPtr&.windowFramePtr& = srcPort& 'set windowFrame ' offPort& = FN SWGetBestPort&(rectPtr&) 'create backFrame LONG IF offPort& err = _NoErr 'initialize function return var spriteWorldPtr&.backFramePtr&=offPort& 'create loadFrame offPort& = FN SWGetBestPort&(rectPtr&) LONG IF offPort& spriteWorldPtr&.loadFramePtr& = offPort& spriteWorldPtr&.backpictHdl& = pictHdl& 'set backPict XELSE err = _swOutOfMemory END IF XELSE err = _swOutOfMemory END IF ' END FN = err ' '--------------------------------------------------------------------- ' SWCreateSWFromWindow '--------------------------------------------------------------------- ' LOCAL MODE LOCAL FN SWCreateSWFromWindow(spriteWorldPtr&,srcPort&) ' ' Creates all associated frames and boundsRect based on a window's ' grafPort. Returns appropriate error code. ' CALL GETGWORLD(CurrPort&,CurrDev&) CALL SETGWORLD(srcPort&,0) ' LONG IF spriteWorldPtr& = _nil 'did we get it? err = _swOutOfMemory 'couldn't allocate pointer XELSE 'got it! pictHdl& = USR GETPICT(#srcPort&+_portRect) 'take snapshot of background ' initialize the new SpriteWorld based on the window err = FN SWCreateSpriteWorld(spriteWorldPtr&,srcPort&,srcPort&+_portRect,pictHdl&) END IF ' CALL SETGWORLD(CurrPort&,CurrDev&) END FN = err ' '--------------------------------------------------------------------- ' SWDisposFrame '--------------------------------------------------------------------- ' LOCAL MODE LOCAL FN SWDisposFrame(framePtr&) CALL DISPOSEGWORLD(framePtr&.imageMapPtr&) CALL DISPOSEGWORLD(framePtr&.maskMapPtr&) END FN = _NoErr ' '--------------------------------------------------------------------- ' SWDisposSprite '--------------------------------------------------------------------- ' ' Disposes of mask region, removes time and frame tasks, and (optionally) ' removes all frames associated with spritePtr&. ' LOCAL MODE LOCAL FN SWDisposSprite(spritePtr&,removeFrames) osErr = 0 CALL DISPOSERGN(spritePtr&.maskRegionHdl&) 'dispose mask region FN RmvTime(spritePtr&+_frameTimeTask&) 'remove time tasks FN RmvTime(spritePtr&+_moveTimeTask&) ' ' if removeFrames = _zTrue, remove all frames contained in this Sprite ' LONG IF removeFrames FOR frame =0 TO spritePtr&.totalFrames%-1 framePtr& = [spritePtr&+_frameList+(frame*4)] osErr = FN SWDisposFrame(framePtr&) IF osErr THEN EXIT FN NEXT END IF ' END FN = osErr ' '--------------------------------------------------------------------- ' SWDisposSpriteWorld '--------------------------------------------------------------------- ' ' Releases memory occupied by SpriteWorld Frames and disposes of any ' sprites contained by SWPtr&. ' LOCAL MODE LOCAL FN SWDisposSpriteWorld(SWPtr&) ' osErr = _NoErr CALL DISPOSEGWORLD(SWPtr&.backFramePtr&) 'delete backFrame CALL DISPOSEGWORLD(SWPtr&.loadFramePtr&) 'and loadFrame... ' FOR layer = 0 TO SWPtr&.totalLayers%-1 'delete all image and mask frames... layerPtr&=[SWPtr&+_layerList+(layer*4)] FOR sprite=0 TO {layerPtr&+_totalSprites}-1 spritePtr& = [layerPtr&+_spriteList+(sprite*4)] ' ' dispose sprite and remove frames if not cloned… ' osErr = FN SWDisposSprite(spritePtr&,spritePtr&.isClone% = 0) IF osErr THEN EXIT FN NEXT NEXT KILL PICTURE SWPtr&.backPictHdl& END FN = osErr ' '--------------------------------------------------------------------- ' SWUpdateSpriteWorld '--------------------------------------------------------------------- ' ' Copies backPict to backFrame and refreshes loadframe. ' LOCAL MODE DIM tempRect.8 LOCAL FN SWRefreshBackground(SWPtr&) ' tempRect;8 = SWPtr&+_boundsRect CALL GETGWORLD(CurrPort&,CurrDev&) ' GW& = SWPtr&.backFramePtr& locked = FN LOCKPIXELS(GW&.portpixmap&) CALL SETGWORLD(GW&,0) CALL DRAWPICTURE(SWPtr&.backPictHdl&,tempRect) 'draw picture to backFrame CALL UNLOCKPIXELS(GW&.portpixmap&) ' GW& = SWPtr&.loadFramePtr& locked = FN LOCKPIXELS(GW&.portpixmap&) CALL SETGWORLD(GW&,0) 'refresh loadFrame with background FN CopyOffScreenBits(SWPtr&.backFramePtr&,GW&,@tempRect,@tempRect,_srcCopy,0) CALL UNLOCKPIXELS(GW&.portpixmap&) ' CALL SETGWORLD(CurrPort&,CurrDev&) ' END FN ' '--------------------------------------------------------------------- ' SWSetBackgroundPict '--------------------------------------------------------------------- ' ' Sets the background PICT to pictHdl&. This background will not ' appear on the screen until you call SWRefreshBackground. ' LOCAL MODE LOCAL FN SWSetBackgroundPict(SWPtr&,pictHdl&) SWPtr&.backPictHdl& = pictHdl& END FN ' '--------------------------------------------------------------------- ' SWProcessSpriteWorld '--------------------------------------------------------------------- ' ' Sets current rect and frame for each sprite ' LOCAL MODE LOCAL FN SWProcessSpriteWorld(SWPtr&) FOR layer = 0 TO SWPtr&.totalLayers%-1 layerPtr& = [SWPtr&+_layerList+(layer*4)] FOR sprite = 0 TO layerPtr&.totalSprites%-1 spritePtr& = [layerPtr&+_spriteList+(sprite*4)]'set current frame... LONG IF spritePtr&.frameTTHasFired% ' curFrame = spritePtr&.currentFrameNum% + spritePtr&.frameAdvance% LONG IF spritePtr&.frameAdvance% > 0 IF curFrame > spritePtr&.lastFrameIndex%-1 THEN curFrame = spritePtr&.firstFrameIndex% XELSE IF curFrame < spritePtr&.firstFrameIndex% THEN curFrame = spritePtr&.lastFrameIndex%-1 END IF ' ' is there a frame change callback? ' frameChangeProcPtr& = spritePtr&.frameChangeProcPtr& ' ' if so, call it… ' IF frameChangeProcPtr& THEN CALL frameChangeProcPtr&(spritePtr&,curFrame) spritePtr&.currentFrameNum% = curFrame ' ' update frame time task ' LONG IF spritePtr&.frameTimeInterval% > 0 spritePtr&.frameTTHasFired% = _false ' •••• FN PrimeTime(spritePtr&+_frameTimeTask&,spritePtr&.frameTimeInterval%) END IF ' ' set draw & erase flags ' LONG IF spritePtr&.isVisible% spritePtr&.needsToBeDrawn% = _zTrue spritePtr&.needsToBeErased% = _zTrue END IF ' END IF ' ' move sprite.... ' LONG IF spritePtr&.moveTTHasFired% ' moveProcPtr& = spritePtr&.moveProcPtr& 'call moveProc CALL moveProcPtr&(SWPtr&,spritePtr&,spritePtr&+_currentRect) ' FN FastOffsetRect(spritePtr&.currentRect%,spritePtr&.xDelta%,spritePtr&.yDelta%) ' update move time task LONG IF spritePtr&.moveTimeInterval% > 0 spritePtr&.moveTTHasFired% = _false FN PrimeTime(spritePtr&+_moveTimeTask&,spritePtr&.moveTimeInterval%) END IF ' ' set draw & erase flags ' LONG IF spritePtr&.isVisible% spritePtr&.needsToBeDrawn% = _zTrue spritePtr&.needsToBeErased% = _zTrue END IF ' END IF NEXT NEXT END FN '--------------------------------------------------------------------- ' SWAnimateSpriteWorld '--------------------------------------------------------------------- ' ' Draws sprites onto loadFrame and copies appropriate portions of ' loadFrame to screen. ' LOCAL MODE DIM tempRect.8 LOCAL FN SWAnimateSpriteWorld(SWPtr&) ' CALL GETGWORLD(CurrPort&,CurrDev&) ' locked = FN LOCKPIXELS(FN GETGWORLDPIXMAP(SWPtr&.loadFramePtr&)) CALL SETGWORLD(SWPtr&.loadFramePtr&,0) ' FOR layer = 0 TO SWPtr&.totalLayers%-1 'erase sprites layerPtr& = [SWPtr&+_layerList+(layer*4)] FOR sprite = 0 TO layerPtr&.totalSprites%-1 spritePtr& = [layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeErased% ' erase sprite by copying piece of backFrame to loadFrame FN CopyOffScreenBits(SWPtr&.backFramePtr&,SWPtr&.loadFramePtr&,spritePtr&+_oldRect,spritePtr&+_oldRect,_srcCopy,_nil) ' check to see if we erased any non-moving sprites… FOR tgtLayer = 0 TO SWPtr&.totalLayers%-1 tgtLayerPtr& = [SWPtr&+_layerList+(tgtLayer*4)] FOR tgtSprite = 0 TO tgtLayerPtr&.totalSprites%-1 tgtSpritePtr& = [tgtLayerPtr&+_spriteList+(tgtSprite*4)] LONG IF tgtSpritePtr&.needsToBeDrawn%=_false AND tgtSpritePtr&.isVisible% LONG IF FN SECTRECT(#spritePtr&+_oldRect,#tgtSpritePtr&+_currentRect,tempRect) ' …if so, make sure we redraw them tgtSpritePtr&.drawPartial% = _zTrue ' get union of deltaRect and tempRect (faster than UnionRect!) IF tgtSpritePtr&.deltaRect.top% > tempRect.top% THEN tgtSpritePtr&.deltaRect.top% = tempRect.top% IF tgtSpritePtr&.deltaRect.left% > tempRect.left% THEN tgtSpritePtr&.deltaRect.left% = tempRect.left% IF tgtSpritePtr&.deltaRect.bottom%< tempRect.bottom% THEN tgtSpritePtr&.deltaRect.bottom%= tempRect.bottom% IF tgtSpritePtr&.deltaRect.right% < tempRect.right% THEN tgtSpritePtr&.deltaRect.right% = tempRect.right% END IF END IF NEXT NEXT END IF NEXT NEXT ' ' draw sprites in their new positions ' FOR layer = 0 TO SWPtr&.totalLayers%-1 layerPtr& = [SWPtr&+_layerList+(layer*4)] FOR sprite = 0 TO layerPtr&.totalSprites%-1 spritePtr& = [layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeDrawn% OR spritePtr&.drawPartial% LONG IF spritePtr&.drawPartial% CALL RECTRGN(spritePtr&.maskRegionHdl&,spritePtr&.deltaRect&) maskRgnHdl& = spritePtr&.maskRegionHdl& spritePtr&.drawPartial% = _false spritePtr&.deltaRect.top& = 0 'clear deltaRect spritePtr&.deltaRect.Bottom& = 0 XELSE maskRgnHdl& = _nil END IF framePtr& = [spritePtr&+_frameList+({spritePtr&+_currentFrameNum}*4)] ' draw mask frame FN CopyOffScreenBits(framePtr&.maskMapPtr&,SWPtr&.loadFramePtr&,framePtr&+_fBoundsRect,spritePtr&+_currentRect,_srcBic,maskRgnHdl&) ' draw image frame FN CopyOffScreenBits(framePtr&.imageMapPtr&,SWPtr&.loadFramePtr&,framePtr&+_fBoundsRect,spritePtr&+_currentRect,_srcOr,maskRgnHdl&) END IF NEXT NEXT ' CALL UNLOCKPIXELS(FN GETGWORLDPIXMAP(SWPtr&.loadFramePtr&)) ' CALL SETGWORLD(SWPtr&.windowFramePtr&,0) ' ' copy loadFrame to screen ' FOR layer = 0 TO SWPtr&.totalLayers%-1 layerPtr& = [SWPtr&+_layerList+(layer*4)] FOR sprite = 0 TO layerPtr&.totalSprites%-1 spritePtr& = [layerPtr&+_spriteList+(sprite*4)] LONG IF spritePtr&.needsToBeDrawn% OR spritePtr&.needsToBeErased% 'get union of oldRect and newRect (faster than UnionRect!) IF spritePtr&.currentRect.top% > spritePtr&.oldRect.top% THEN spritePtr&.deltaRect.top% = spritePtr&.oldRect.top% ELSE spritePtr&.deltaRect.top% = spritePtr&.currentRect.top% IF spritePtr&.currentRect.left% > spritePtr&.oldRect.left% THEN spritePtr&.deltaRect.left% = spritePtr&.oldRect.left% ELSE spritePtr&.deltaRect.left% = spritePtr&.currentRect.left% IF spritePtr&.currentRect.bottom% < spritePtr&.oldRect.bottom% THEN spritePtr&.deltaRect.bottom% = spritePtr&.oldRect.bottom% ELSE spritePtr&.deltaRect.bottom% = spritePtr&.currentRect.bottom% IF spritePtr&.currentRect.right% < spritePtr&.oldRect.right% THEN spritePtr&.deltaRect.right% = spritePtr&.oldRect.right% ELSE spritePtr&.deltaRect.right% = spritePtr&.currentRect.right% 'set mask region equal to deltaRect CALL RECTRGN(spritePtr&.maskRegionHdl&,#spritePtr&+_deltaRect) FN CopyOffScreenBits(SWPtr&.loadFramePtr&,SWPtr&.windowFramePtr&,spritePtr&+_deltaRect,spritePtr&+_deltaRect,_srcCopy,spritePtr&.maskRegionHdl&) spritePtr&.needsToBeDrawn% = _false 'clear draw & erase flags spritePtr&.needsToBeErased% = _false END IF spritePtr&.oldRect%;8 = spritePtr&+_currentRect'set old rect NEXT NEXT CALL SETGWORLD(CurrPort&,CurrDev&) END FN ' '--------------------------------------------------------------------- ' SWAddLayerToWorld '--------------------------------------------------------------------- ' ' Adds layerPtr& to specified SpriteWorld. ' LOCAL MODE LOCAL FN SWAddLayerToWorld(SWPtr&,layerPtr&) ' LONG IF SWPtr&.totalLayers%<_maxLayers err = _NoErr offset = SWPtr&.totalLayers%*4 POKE LONG SWPtr&+_layerList+offset,layerPtr& INC(SWPtr&.totalLayers%) XELSE err=_swTooManyLayers END IF ' END FN = err ' '--------------------------------------------------------------------- ' SWFrameFromPict '--------------------------------------------------------------------- ' ' Creates image and mask frames from specified PICT resource. ' LOCAL MODE DIM frameRect.8 LOCAL FN SWFrameFromPict(framePtr&,pictID) err = _NoErr CALL GETGWORLD(CurrPort&,CurrDev&) ' ' create imageFrame... ' pict& = FN GETPICTURE(pictID) : err = FN RESERROR ' LONG IF err=_noErr frameRect;8 = [pict&]+_picFrame ' make sure we're at 0,0 FN FastOffsetRect(frameRect,-frameRect.left%,-frameRect.top%) framePtr&.fBoundsRect%;8 = @frameRect 'copy frameRect to FramePtr.fBoundsRect offPort& = FN SWGetBestPort&(@frameRect) 'create off screen port for image LONG IF offPort& framePtr&.imageMapPtr&=offPort& locked = FN LOCKPIXELS(offPort&.portpixmap&) CALL SETGWORLD(offPort&,0) 'FN SetThePort(offPort&) CALL DRAWPICTURE(pict&,frameRect) 'draw picture to imageFrame CALL UNLOCKPIXELS(offPort&.portpixmap&) CALL RELEASERESOURCE(pict&) XELSE err=_swOutOfMemory END IF ' ' create maskFrame... ' pict& = FN GETPICTURE(pictID + 2) : err = FN RESERROR ' LONG IF err=_noErr offPort& = FN SWGetBestPort&(@frameRect) 'create off screen port for mask LONG IF offPort& framePtr&.maskMapPtr& = offPort& locked = FN LOCKPIXELS(offPort&.portpixmap&) CALL SETGWORLD(offPort&,0) 'FN SetThePort(offPort&) CALL DRAWPICTURE(pict&,frameRect) 'draw picture to imageFrame CALL UNLOCKPIXELS(offPort&.portpixmap&) CALL RELEASERESOURCE(pict&) XELSE err=_swOutOfMemory END IF END IF END IF ' CALL SETGWORLD(CurrPort&,CurrDev&) ' END FN = err ' '--------------------------------------------------------------------- ' SWAddFrameToSprite '--------------------------------------------------------------------- ' ' Adds framePtr& to specified sprite. ' LOCAL MODE LOCAL FN SWAddFrameToSprite(spritePtr&,framePtr&) LONG IF spritePtr&.totalFrames% < _maxFrames err = _NoErr offset = spritePtr&.totalFrames%*4 POKE LONG spritePtr&+_frameList+offset,framePtr& INC(spritePtr&.totalframes%) spritePtr&.lastFrameIndex%=spritePtr&.totalFrames% XELSE err=_swTooManyFrames END IF END FN = err ' '--------------------------------------------------------------------- ' SWInitSprite '--------------------------------------------------------------------- ' ' Given a pointer to a previously dimmed Sprite, sets initial values ' of a Sprite. ' LOCAL MODE LOCAL FN SWInitSprite(spritePtr&,curFrame,curRectP&,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&) ' spritePtr&.currentFrameNum%=curFrame BLOCKMOVE curRectP&,spritePtr&+_currentRect,8 BLOCKMOVE curRectP&,spritePtr&+_oldRect,8 BLOCKMOVE boundsRectP&,spritePtr&+_sBoundsRect,8 spritePtr&.isVisible% = vis spritePtr&.needsToBeErased% = _false spritePtr&.needsToBeDrawn% = _zTrue spritePtr&.drawPartial% = _false spritePtr&.totalFrames% = 0 spritePtr&.firstFrameIndex% = 0 spritePtr&.lastFrameIndex% = 0 spritePtr&.xDelta% = xDelta spritePtr&.yDelta% = yDelta spritePtr&.maskRegionHdl& = FN NEWRGN spritePtr&.frameAdvance% = frameAdvance spritePtr&.frameTimeTask.qLink& = _nil spritePtr&.frameTimeTask.qType% = 0 spritePtr&.frameTimeTask.tmAddr& = ttPtr& spritePtr&.frameTimeTask.tmCount& = 0 spritePtr&.frameTimeTask.tmWakeUp& = 0 spritePtr&.frameTimeTask.tmReserved& = 0 spritePtr&.frameTTHasFired% = _zTrue spritePtr&.frameTimeInterval% = 0 spritePtr&.frameChangeProcPtr& = _nil spritePtr&.moveTimeTask.qLink& = _nil spritePtr&.moveTimeTask.qType% = 0 spritePtr&.moveTimeTask.tmAddr& = ttPtr& spritePtr&.moveTimeTask.tmCount& = 0 spritePtr&.moveTimeTask.tmWakeUp& = 0 spritePtr&.moveTimeTask.tmReserved& = 0 spritePtr&.moveTTHasFired% = _zTrue spritePtr&.moveTimeInterval% = 0 spritePtr&.moveProcPtr& = movePtr& spritePtr&.collideProcPtr& = _nil spritePtr&.isClone% = _false ' FN InsXTime(spritePtr&.frameTimeTask&) 'install time tasks FN InsXTime(spritePtr&.moveTimeTask&) ' END FN ' '--------------------------------------------------------------------- ' SWCloneSprite '--------------------------------------------------------------------- ' ' A cloned sprite is an exact duplicate of its source. If you have ' assigned frames to the source sprite, the framelist of the clone ' will contain pointers to those same frames. Thus, cloned sprites ' can share the same frames with their sources, which saves memory ' and processing time. The isClone field is set TRUE for cloned ' sprites, so we can determine whether to remove frames from memory ' when disposing of a sprite (generally, you will only remove frames ' when disposing of a non-cloned sprite). ' LOCAL MODE LOCAL FN SWCloneSprite(srcSpritePtr&,cloneSpritePtr&,ttPtr&) ' copy srcSprite data to cloneSprite BLOCKMOVE srcSpritePtr&,cloneSpritePtr&,_SWSpriteRec ' frame time tasks are unique to each sprite… cloneSpritePtr&.frameTimeTask.qLink& = _nil cloneSpritePtr&.frameTimeTask.qType% = 0 cloneSpritePtr&.frameTimeTask.tmAddr& = ttPtr& cloneSpritePtr&.frameTimeTask.tmCount&= 0 cloneSpritePtr&.frameTimeTask.tmWakeUp&=0 cloneSpritePtr&.frameTimeTask.tmReserved&=0 cloneSpritePtr&.frameTTHasFired% = _zTrue cloneSpritePtr&.frameTimeInterval% = 0 ' so are mask regions… ' •••• cloneSpritePtr&.maskRegionHdl& = FN NEWRGN ' and so are move time tasks… cloneSpritePtr&.moveTimeTask.qLink& = _nil cloneSpritePtr&.moveTimeTask.qType% = 0 cloneSpritePtr&.moveTimeTask.tmAddr& = ttPtr& cloneSpritePtr&.moveTimeTask.tmCount& = 0 cloneSpritePtr&.moveTimeTask.tmWakeUp&= 0 cloneSpritePtr&.moveTimeTask.tmReserved&= 0 cloneSpritePtr&.moveTTHasFired% = _zTrue cloneSpritePtr&.moveTimeInterval% = 0 cloneSpritePtr&.isClone% = _zTrue 'mark sprite as cloned FN InsXTime(cloneSpritePtr&.frameTimeTask&) 'install time tasks FN InsXTime(cloneSpritePtr&.moveTimeTask&) END FN ' '--------------------------------------------------------------------- ' SWSpriteFromPict '--------------------------------------------------------------------- ' ' Inits a Sprite based on pictID (that is, its curRect field is based ' on the size of pictID, offset to curX,curY. Returns resErr. ' LOCAL MODE DIM frameRect.8 LOCAL FN SWSpriteFromPict(spritePtr&,curFrame,curX,curY,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&,pictID) ' pict& = FN GETPICTURE(pictID) : resErr = FN RESERROR ' LONG IF resErr = _noErr frameRect;8 = [pict&]+_picFrame 'pin rect to curX,curY… FN FastOffsetRect(frameRect,curX-frameRect.left%,curY-frameRect.top%) FN SWInitSprite(spritePtr&,curFrame,@frameRect,boundsRectP&,vis,xDelta,yDelta,frameAdvance,ttPtr&,movePtr&) CALL RELEASERESOURCE(pict&) END IF ' END FN = resErr ' '--------------------------------------------------------------------- ' SWAddSpriteToLayer '--------------------------------------------------------------------- ' ' Adds spritePtr& to the specified layer. ' LOCAL MODE LOCAL FN SWAddSpriteToLayer(layerPtr&,spritePtr&) ' LONG IF layerPtr&.totalSprites% < _maxSprites err = _NoErr offset=layerPtr&.totalSprites%*4 POKE LONG layerPtr&+_spriteList+offset,spritePtr& INC(layerPtr&.totalSprites%) XELSE err=_swTooManySprites END IF ' END FN = err '--------------------------------------------------------------------- ' SWSetSpriteMoveProc '--------------------------------------------------------------------- ' ' Sets the movement procedure for a sprite. ' LOCAL MODE LOCAL FN SWSetSpriteMoveProc(spritePtr&,moveProcPtr&) spritePtr&.moveProcPtr& = moveProcPtr& END FN ' '--------------------------------------------------------------------- ' SWSetCollideProc '--------------------------------------------------------------------- ' ' Set the collide procedure for a sprite. ' LOCAL MODE LOCAL FN SWSetCollideProc(spritePtr&,collideProcPtr&) spritePtr&.collideProcPtr& = collideProcPtr& END FN ' '--------------------------------------------------------------------- ' SWSetFrameChangeProc '--------------------------------------------------------------------- ' ' Sets the frame change procedure for a sprite. ' LOCAL MODE LOCAL FN SWSetFrameChangeProc(spritePtr&,frameChangeProcPtr&) spritePtr&.frameChangeProcPtr& = frameChangeProcPtr& END FN ' '--------------------------------------------------------------------- ' SWSetMoveDelta '--------------------------------------------------------------------- ' ' Sets the number of pixels a sprite should be moved by ' SWProcessSpriteWorld horizontally and vertically. ' LOCAL MODE LOCAL FN SWSetMoveDelta(spritePtr&,xDelta,yDelta) spritePtr&.xDelta% = xDelta spritePtr&.yDelta% = yDelta END FN ' '--------------------------------------------------------------------- ' SWOffsetSprite '--------------------------------------------------------------------- ' ' Moves sprite to a relative position on the screen. ' LOCAL MODE LOCAL FN SWOffsetSprite(spritePtr&,xDelta,yDelta) FN FastOffsetRect(spritePtr&.currentRect%,xDelta,yDelta) LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased% = _zTrue spritePtr&.needsToBeDrawn% = _zTrue END IF END FN '--------------------------------------------------------------------- ' SWSetSpriteFrameAdv '--------------------------------------------------------------------- ' ' Sets the number by which SWProcessSpriteWorld will advance the current ' frame. ' LOCAL MODE LOCAL FN SWSetSpriteFrameAdv(spritePtr&,frameAdv) spritePtr&.frameAdvance% = frameAdv END FN '--------------------------------------------------------------------- ' SWSetCurrentFrame '--------------------------------------------------------------------- ' ' Sets the sprite's current frame. ' LOCAL MODE LOCAL FN SWSetCurrentFrame(spritePtr&,frameNum) spritePtr&.currentFrameNum% = frameNum END FN '--------------------------------------------------------------------- ' SWSetSpriteVisible '--------------------------------------------------------------------- ' ' Causes a sprite to appear or disappear. ' LOCAL MODE LOCAL FN SWSetSpriteVisible(spritePtr&,vis) spritePtr&.isVisible% = vis spritePtr&.needsToBeDrawn% = vis spritePtr&.needsToBeErased% = NOT(vis) END FN ' '--------------------------------------------------------------------- ' SWGetCurRect '--------------------------------------------------------------------- ' ' Returns sprite's currentRect. ' LOCAL MODE LOCAL FN SWGetCurRect(spritePtr&,T&) T&.Top%;8 = spritePtr&+_currentRect END FN ' '--------------------------------------------------------------------- ' SWSetCurRect '--------------------------------------------------------------------- ' ' Sets current and old rect of sprite. ' LOCAL MODE LOCAL FN SWSetCurRect(spritePtr&,T&) spritePtr&.currentRect%;8 = T& spritePtr&.oldRect%;8 = T& END FN ' '--------------------------------------------------------------------- ' SWSetSpriteLocation '--------------------------------------------------------------------- ' ' Sets current and old location of sprite, based on x,y coordinates. ' LOCAL MODE LOCAL FN SWSetSpriteLocation(spritePtr&,x,y) FN FastOffsetRect(spritePtr&.currentRect%,x-spritePtr&.currentRect.left%,y-spritePtr&.currentRect.top%) spritePtr&.oldRect%;8 = spritePtr&+_currentRect END FN '--------------------------------------------------------------------- ' SWMoveSpriteRect '--------------------------------------------------------------------- ' ' Moves sprite to new rectangle. ' LOCAL MODE LOCAL FN SWMoveSpriteRect(spritePtr&,T&) spritePtr&.currentRect%;8 = T& LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased% = _zTrue spritePtr&.needsToBeDrawn% = _zTrue END IF END FN ' '--------------------------------------------------------------------- ' SWMoveSprite '--------------------------------------------------------------------- ' ' Moves sprite to new x,y coordinates. ' LOCAL MODE LOCAL FN SWMoveSprite(spritePtr&,x,y) ' FN FastOffsetRect(spritePtr&.currentRect%,x-spritePtr&.currentRect.left%,y-spritePtr&.currentRect.top%) ' LONG IF spritePtr&.isVisible% spritePtr&.needsToBeErased% = _zTrue spritePtr&.needsToBeDrawn% = _zTrue END IF END FN ' '--------------------------------------------------------------------- ' SWSetMoveBounds '--------------------------------------------------------------------- ' ' Sets the bounding rectangle of the specified sprite. ' LOCAL MODE LOCAL FN SWSetMoveBounds(spritePtr&,T&) spritePtr&.sBoundsRect%;8 = T& END FN ' '--------------------------------------------------------------------- ' SWSetFrameRange '--------------------------------------------------------------------- ' ' Sets the range of frame indexes to be interated in SWProcessSpriteWorld. ' LOCAL MODE LOCAL FN SWSetFrameRange(spritePtr&,firstFrame,lastFrame) spritePtr&.firstFrameIndex% = firstFrame spritePtr&.lastFrameIndex% = lastFrame END FN ' '--------------------------------------------------------------------- ' SWIsSpriteInRect '--------------------------------------------------------------------- ' LOCAL MODE DIM rect.8 LOCAL FN SWIsSpriteInRect(spritePtr&,rect;8) ' ' Returns _zTrue (-1) if sprite's current rect is equal to or ' contained in rect. ' END FN = (spritePtr&.currentRect.top%>=rect.top% AND spritePtr&.currentRect.left%>=rect.left% AND spritePtr&.currentRect.bottom%<=rect.bottom% AND spritePtr&.currentRect.right%<=rect.right%) ' '--------------------------------------------------------------------- ' SWSpriteSectRect '--------------------------------------------------------------------- ' LOCAL MODE DIM rect.8 LOCAL FN SWSpriteSectRect(spritePtr&,rect;8,sectRectPtr&) ' ' Returns _zTrue (-1) if the sprite's current rect intersects ' rect. If there is an intersection, sectRect will contain the ' intersecting rectangle. ' END FN = -(FN SECTRECT(#spritePtr&+_currentRect,rect,#sectRectPtr&)) ' '--------------------------------------------------------------------- ' SWRemoveLayer '--------------------------------------------------------------------- ' ' Removes a layer from the specified SpriteWorld. ' LOCAL MODE LOCAL FN SWRemoveLayer(SWPtr&,layerPtr&) ' FOR x = 0 TO SWPtr&.totalLayers%-1 'find layer in layerlist targetLayer& = [SWPtr&+_layerList+(x*4)] LONG IF layerPtr& = targetLayer& ' delete layer and adjust layerList FOR layer = x TO SWPtr&.totalLayers%-2 &SWPtr&+_layerList+(layer*4),[SWPtr&+_layerList+((layer+1)*4)] NEXT &SWPtr&+_layerList+((SWPtr&.totalLayers%-1)*4),_nil DEC(SWPtr&.totalLayers%) EXIT FOR END IF NEXT ' END FN ' '--------------------------------------------------------------------- ' SWRemoveSprite '--------------------------------------------------------------------- ' ' Removes a sprite from the specified layer. ' Does not dispose of the sprite. ' LOCAL MODE LOCAL FN SWRemoveSprite(layerPtr&,spritePtr&) ' FOR x = 0 TO layerPtr&.totalSprites%-1 'find sprite in spritelist targetSprite& = [layerPtr&+_spriteList+(x*4)] LONG IF spritePtr& = targetSprite& ' delete sprite and adjust spriteList FOR sprite=x TO layerPtr&.totalSprites%-2 &layerPtr&+_spriteList+(sprite*4),[layerPtr&+_spriteList+((sprite+1)*4)] NEXT &layerPtr&+_spriteList+((layerPtr&.totalSprites%-1)*4),_nil DEC(layerPtr&.totalSprites%) EXIT FOR END IF NEXT ' END FN ' '--------------------------------------------------------------------- ' SWRemoveFrame '--------------------------------------------------------------------- ' ' Removes a frame from the specified sprite. ' Does not dispose of the frame. ' LOCAL MODE LOCAL FN SWRemoveFrame(spritePtr&,framePtr&) ' FOR x = 0 TO spritePtr&.totalFrames%-1 'find frame in framelist targetFrame& = [spritePtr&+_frameList+(x*4)] LONG IF framePtr& = targetFrame& ' delete frame and adjust frameList FOR frame = x TO spritePtr&.totalFrames%-2 &spritePtr&+_frameList+(frame*4),[spritePtr&+_frameList+((frame+1)*4)] NEXT &spritePtr&+_frameList+((spritePtr&.totalFrames%-1)*4),_nil DEC(spritePtr&.totalFrames%) ' adjust lastFrameIndex, if necessary IF spritePtr&.totalFrames%<spritePtr&.lastFrameIndex% THEN spritePtr&.lastFrameIndex%=spritePtr&.totalFrames% EXIT FOR END IF NEXT ' END FN ' '--------------------------------------------------------------------- ' SWIsTaskPrimed '--------------------------------------------------------------------- ' LOCAL MODE LOCAL FN SWIsTaskPrimed(tmTaskPtr&) ' ' Returns _zTrue if timeTask has been primed. ' END FN = (tmTaskPtr&.qType% AND &8000) <> 0 ' '--------------------------------------------------------------------- ' SWSetFrameTime '--------------------------------------------------------------------- ' ' Sets the time in milliseconds between frame changes. ' LOCAL MODE LOCAL FN SWSetFrameTime(spritePtr&,timeInterval) ' spritePtr&.frameTimeInterval% = timeInterval LONG IF timeInterval > 0 LONG IF FN SWIsTaskPrimed(spritePtr&.frameTimeTask&)=0'if task not primed… spritePtr&.frameTTHasFired% = _zTrue '…prime it END IF XELSE LONG IF timeInterval < 0 'is the time interval negative? LONG IF FN SWIsTaskPrimed(spritePtr&.frameTimeTask&)'if the task is primed… FN RmvTime(spritePtr&.frameTimeTask&) '…remove it FN InsXTime(spritePtr&.frameTimeTask&) END IF ' the timeInterval is negative, which means never change the frame spritePtr&.frameTTHasFired% = _false XELSE ' time interval=0; this means change frames as quickly as possible spritePtr&.frameTTHasFired% = _zTrue END IF END IF ' END FN ' '--------------------------------------------------------------------- ' SWSetMoveTime '--------------------------------------------------------------------- ' ' Sets the time in milliseconds between sprite moves. ' LOCAL MODE LOCAL FN SWSetMoveTime(spritePtr&,timeInterval) ' spritePtr&.moveTimeInterval% = timeInterval ' LONG IF timeInterval > 0 LONG IF FN SWIsTaskPrimed(spritePtr&.moveTimeTask&)=0'if task not primed… spritePtr&.moveTTHasFired% = _zTrue '…prime it END IF XELSE LONG IF timeInterval < 0 'is the time interval negative? LONG IF FN SWIsTaskPrimed(spritePtr&.moveTimeTask&)'if the task is primed… FN RmvTime(spritePtr&.moveTimeTask&) 'remove it FN InsXTime(spritePtr&.moveTimeTask&) END IF ' ' the timeInterval is negative, which means never move sprite ' spritePtr&.moveTTHasFired% = _false XELSE ' ' time interval=0; this means move sprite as quickly as possible ' spritePtr&.moveTTHasFired% = _zTrue END IF END IF END FN ' '--------------------------------------------------------------------- ' SWUpdateSpriteWorld '--------------------------------------------------------------------- ' ' Copies entire loadframe to screen. ' Used to refesh screen following an update event. ' LOCAL MODE LOCAL FN SWUpdateSpriteWorld(SWPtr&) FN CopyOffScreenBits(SWPtr&.loadFramePtr&,SWPtr&.windowFramePtr&,SWPtr&+_boundsRect,SWPtr&+_boundsRect,_srcCopy,_nil) END FN ' '--------------------------------------------------------------------- ' SWCollideSpriteLayer '--------------------------------------------------------------------- ' ' Detects collisions between sprites in srcLayer and sprites in ' destLayer. If collision is detected, calls collideProc of srcSprite. ' To detect collisions between sprites in the same layer, pass the ' same layer variable in both srcLayerPtr& and destLayerPtr&. ' LOCAL MODE DIM sectRect.8 LOCAL FN SWCollideSpriteLayer(srcLayerPtr&,destLayerPtr&) ' FOR srcSprite = 0 TO srcLayerPtr&.totalSprites%-1 srcSpritePtr& = [srcLayerPtr&+_spriteList+(srcSprite*4)] ' FOR destSprite = 0 TO destLayerPtr&.totalSprites%-1 destSpritePtr& = [destLayerPtr&+_spriteList+(destSprite*4)] LONG IF srcSpritePtr& <> destSpritePtr& LONG IF FN SECTRECT(#srcSpritePtr&+_currentRect,#destSpritePtr&+_currentRect,sectRect) collideProcPtr& = srcSpritePtr&.collideProcPtr& IF collideProcPtr& THEN CALL collideProcPtr&(srcSpritePtr&,destSpritePtr&,@sectRect) END IF END IF NEXT ' NEXT ' END FN ' '• • • • • • • • • •